#include "color.h"


color::color()
{
	r = 0.0f;
	g = 0.0f;
	b = 0.0f;
	a = 0.0f;
}
color::color(float R, float G, float B, float A)
{
	r = R;
	g = G;
	b = B;
	a = A;
}
color::color(float R, float G, float B)
{
	r = R;
	g = G;
	b = B;
	a = 1.0f;
}
color::color(float RGB)
{
	r = RGB;
	g = RGB;
	b = RGB;
	a = 1.0f;
}
color::color(int R, int G, int B, int A)
{
	r = (float)R/255.0f;
	g = (float)G/255.0f;
	b = (float)B/255.0f;
	a = (float)A/255.0f;	
}
color::color(int R, int G, int B)
{
	r = (float)R/255.0f;
	g = (float)G/255.0f;
	b = (float)B/255.0f;
	a = 1.0f;
}
color::color(std::string colorName)
{
	if (std::strcmp(colorName.c_str(),"black"))
	{
		r = 0.0f;
		g = 0.0f;
		b = 0.0f;
		a = 1.0f;
	}
	if (std::strcmp(colorName.c_str(),"white"))
	{
		r = 1.0f;
		g = 1.0f;
		b = 1.0f;
		a = 1.0f;
	}
	if (std::strcmp(colorName.c_str(),"red"))
	{
		r = 1.0f;
		g = 0.0f;
		b = 0.0f;
		a = 1.0f;
	}
	if (std::strcmp(colorName.c_str(),"blue"))
	{
		r = 0.0f;
		g = 0.0f;
		b = 1.0f;
		a = 1.0f;
	}
	if (std::strcmp(colorName.c_str(),"green"))
	{
		r = 0.0f;
		g = 1.0f;
		b = 0.0f;
		a = 1.0f;
	}

}
color::~color()
{

}
void color::getColorFromXML(std::ifstream &file)
{
	char line[MAX_LENGTH];
	file.getline(line, MAX_LENGTH);
	std::string nazwaWezla;
	std::string temp(line);

	unsigned int i(0);

	while(temp[i] == 9 || temp[i] == 32)
		++i;

	++i;
	while(temp[i] != '>')
	{
		nazwaWezla.push_back(temp[i]);
		++i;
	}
	while (nazwaWezla!="/color")
	{
		file.getline(line, MAX_LENGTH);
		temp.clear();
		temp.append(line);
		nazwaWezla.clear();

		i=0;
		while(temp[i] == 9 || temp[i] == 32)
			++i;
		if(temp[i] == '<')
		{
			std::string nazwaWezlaKoniec;
			std::string zawartoscWezla;
			++i;
			while(temp[i] != '>')
			{
				nazwaWezla.push_back(temp[i]);
				++i;
			}
			if(nazwaWezla == "R")
			{
				++i;
				while(temp[i] != '<')
				{
					zawartoscWezla.push_back(temp[i]);
					++i;
				}
				++i;
				while(temp[i] != '>')
				{
					nazwaWezlaKoniec.push_back(temp[i]);
					++i;
				}
				if(nazwaWezlaKoniec == "/R")
					this->r = (float)atof(zawartoscWezla.c_str());
				continue;
			}
			else if(nazwaWezla == "G")
			{
				++i;
				while(temp[i] != '<')
				{
					zawartoscWezla.push_back(temp[i]);
					++i;
				}
				++i;
				while(temp[i] != '>')
				{
					nazwaWezlaKoniec.push_back(temp[i]);
					++i;
				}
				if(nazwaWezlaKoniec == "/G")
					this->g = (float)atof(zawartoscWezla.c_str());
				continue;
			}
			else if(nazwaWezla == "B")
			{
				++i;
				while(temp[i] != '<')
				{
					zawartoscWezla.push_back(temp[i]);
					++i;
				}
				++i;
				while(temp[i] != '>')
				{
					nazwaWezlaKoniec.push_back(temp[i]);
					++i;
				}
				if(nazwaWezlaKoniec == "/B")
					this->b = (float)atof(zawartoscWezla.c_str());
				continue;
			}
			else if(nazwaWezla == "A")
			{
				++i;
				while(temp[i] != '<')
				{
					zawartoscWezla.push_back(temp[i]);
					++i;
				}
				++i;
				while(temp[i] != '>')
				{
					nazwaWezlaKoniec.push_back(temp[i]);
					++i;
				}
				if(nazwaWezlaKoniec == "/A")
					this->a = (float)atof(zawartoscWezla.c_str());
				continue;
			}
		}
	}
}
void color::validate()
{
	if(Exposure == 0)
	{
		if (r < 0.0f)
			r = 0.0;
		if (r > 1.0f)
			r = 1.0f;

		if (g < 0.0f)
			g = 0.0;
		if (g > 1.0f)
			g = 1.0f;

		if (b < 0.0f)
			b = 0.0;
		if (b > 1.0f)
			b = 1.0f;

		if (a < 0.0f)
			a = 0.0;
		if (a > 1.0f)
			a = 1.0f;
	}
	else
	{
		float exposure = -(float)Exposure;
		r = 1.0f - expf(r * exposure);
		g = 1.0f - expf(g * exposure);
		b = 1.0f - expf(b * exposure);
	}
}
void color::setExposure(double exp)
{
	Exposure = exp;
}

void color::setColor(color other)
{
	this->r = other.r;
	this->g = other.g;
	this->b = other.b;
	this->a = other.a;
}
void color::add(color other)
{
	this->r += other.r;
	this->g += other.g;
	this->b	+= other.b;
	this->a	+= other.a;
}
//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++
//Operators
//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++//++
color color::operator+( const color &other )
{
	color temp(this->r + other.r, this->g + other.g, this->b + other.b, this->a + other.a);
	temp.validate();
	return temp;
}
color & color::operator+=( const color &other )
{
	this->r += other.r;
	this->g += other.g;
	this->b	+= other.b;
	this->a	+= other.a;
	this->validate();
	return *this;
}
color color::operator-( const color &other )
{
	color temp(this->r - other.r, this->g - other.g, this->b - other.b, this->a - other.a);
	temp.validate();
	return temp;
}
color & color::operator-=( const color &other )
{
	this->r -= other.r;
	this->g -= other.g;
	this->b	-= other.b;
	this->a	-= other.a;
	this->validate();
	return *this;
}
color color::operator*( const color &other )
{
	color temp;
	temp.r= this->r * other.r;
	temp.g= this->g * other.g;
	temp.b= this->b * other.b;
	temp.a= this->a * other.a;
	temp.validate();
	return temp;
}
color color::operator*( const  double &scalar )
{
	color temp;
	temp.r= this->r * (float)scalar;
	temp.g= this->g * (float)scalar;
	temp.b= this->b * (float)scalar;
	temp.a= this->a * (float)scalar;
	temp.validate();
	return temp;
}
color color::operator*( const float &scalar )
{
	color temp;
	temp.r= this->r * scalar;
	temp.g= this->g * scalar;
	temp.b= this->b * scalar;
	temp.b= this->b * scalar;
	temp.validate();
	return temp;
}
color color::operator*( const int &scalar )
{
	color temp;
	temp.r= this->r * (float)scalar;
	temp.g= this->g * (float)scalar;
	temp.b= this->b * (float)scalar;
	temp.a= this->a * (float)scalar;
	temp.validate();
	return temp;
}
color & color::operator*=( const color &other )
{
	this->r *= other.r;
	this->g *= other.g;
	this->b *= other.b;
	this->a *= other.a;
	this->validate();
	return *this;
}
color & color::operator*=( const double &scalar )
{
	this->r *= (float)scalar;
	this->g *= (float)scalar;
	this->b *= (float)scalar;
	this->a *= (float)scalar;
	this->validate();
	return *this;
}
color & color::operator*=( const float &scalar )
{
	this->r *= scalar;
	this->g *= scalar;
	this->b *= scalar;
	this->a *= scalar;
	this->validate();
	return *this;
}
color & color::operator*=( const int &scalar )
{
	this->r *= (float)scalar;
	this->g *= (float)scalar;
	this->b *= (float)scalar;
	this->a *= (float)scalar;
	this->validate();
	return *this;
}
color color::operator/( const color &other )
{
	color temp;
	temp.r = this->r / other.r;
	temp.g = this->g / other.g;
	temp.b = this->b / other.b;
	temp.a = this->a / other.a;
	temp.validate();
	return temp;
}
color color::operator/( const double &scalar )
{
	color temp;
	temp.r = this->r / (float)scalar;
	temp.g = this->g / (float)scalar;
	temp.b = this->b / (float)scalar;
	temp.a = this->a / (float)scalar;
	temp.validate();
	return temp;
}
color color::operator/( const float &scalar )
{
	color temp;
	temp.r = this->r / scalar;
	temp.g = this->g / scalar;
	temp.b = this->b / scalar;
	temp.a = this->a / scalar;
	temp.validate();
	return temp;

}
color color::operator/( const int &scalar )
{
	color temp;
	temp.r = this->r / (float)scalar;
	temp.g = this->g / (float)scalar;
	temp.b = this->b / (float)scalar;
	temp.a = this->a / (float)scalar;
	temp.validate();
	return temp;
}
color & color::operator/=( const color &other )
{
	this->r /= other.r;
	this->g /= other.g;
	this->b /= other.b;
	this->a /= other.a;
	this->validate();
	return *this;
}
color & color::operator/=( const double &scalar )
{
	this->r /= (float)scalar;
	this->g /= (float)scalar;
	this->b /= (float)scalar;
	this->a /= (float)scalar;
	this->validate();
	return *this;
}
color & color::operator/=( const float &scalar )
{
	this->r /= scalar;
	this->g /= scalar;
	this->b /= scalar;
	this->a /= scalar;
	this->validate();
	return *this;
}
color & color::operator/=( const int &scalar )
{
	this->r /= (float)scalar;
	this->g /= (float)scalar;
	this->b /= (float)scalar;
	this->a /= (float)scalar;
	this->validate();
	return *this;
}
color & color::operator=( const color &other )
{
	this->r = other.r;
	this->g = other.g;
	this->b = other.b;
	this->a = other.a;
	this->validate();
	return *this; 
}
bool color::operator==( const color &other )
{
	if ( (this->r == other.r) && (this->g == other.g) && (this->b == other.b) && (this->a == other.a))
		return true;
	else 
		return false;
}
bool color::operator!=( const color &other )
{
	if ( (this->r == other.r) && (this->g == other.g) && (this->b == other.b) && (this->a == other.a))
		return false;
	else 
		return true;
}

double color::Exposure = 0;